package com.crane.oss.web.controller.school;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.crane.common.core.dto.MultiResponse;
import com.crane.common.core.dto.Response;
import com.crane.common.core.dto.SingleResponse;
import com.crane.common.core.exception.AppException;
import com.crane.common.core.exception.BasicErrorCode;
import com.crane.common.framework.utils.BeanUtil;
import com.crane.oss.listener.UploadClassesExcelListener;
import com.crane.oss.school.bean.request.QueryClassesInfoReq;
import com.crane.oss.school.bean.request.classesinfo.AddClassesInfoReq;
import com.crane.oss.school.bean.request.classesinfo.BatchDeleteClassesInfoReq;
import com.crane.oss.school.bean.request.classesinfo.BatchImportClassesEntity;
import com.crane.oss.school.bean.request.classesinfo.UpdateClassesInfoReq;
import com.crane.oss.school.bean.resp.ClassTeacherResp;
import com.crane.oss.school.bean.resp.ClassesInfoExportResp;
import com.crane.oss.school.bean.resp.ClassesInfoResp;
import com.crane.oss.school.service.ClassesInfoService;
import com.crane.oss.web.BaseBusinessController;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

/**
 * @author zhenxing.pi
 * @email ccsu123456@qq.com
 * @date 2022年03月26日 14时38分15秒
 */

@Api(value = "ClassesInfoController", tags = { "班级管理" })
@RestController
@RequestMapping("/school/classesInfo")
public class ClassesInfoController extends BaseBusinessController {

	@Autowired
	ClassesInfoService classesInfoService;

	@ApiOperation(value = "获取班级列表信息", notes = "获取班级列表信息")
	@ApiImplicitParam(name = "request", value = "请求对象", required = true, dataType = "QueryClassesInfoReq")
	@RequiresPermissions("school:classesinfo:list")
	@PostMapping("/list")
	public MultiResponse<ClassesInfoResp> list(@RequestBody QueryClassesInfoReq request) {
		request.setPartyId(getPartyId());
		IPage<ClassesInfoResp> page = classesInfoService.queryList(request);
		return MultiResponse.of(page.getRecords(), (int) page.getTotal(), request);
	}
	
	@ApiOperation(value = "新增班级", notes = "单个增加班级")
	@ApiImplicitParam(name = "request", value = "请求对象", required = true, dataType = "AddClassesInfoReq")
	@RequiresPermissions("school:classesinfo:save")
	@PostMapping("/save")
	public Response save(@RequestBody @Valid AddClassesInfoReq request) {
		request.setCreateUserId(getUserId());
		classesInfoService.save(request);
		return Response.buildSuccess();
	}
	
	@ApiOperation(value = "班级详情", notes = "班级详情")
	@ApiImplicitParam(name = "classId", value = "班级ID", paramType = "path", dataType = "String")
	@RequiresPermissions("school:classesinfo:info")
	@GetMapping("/info/{classId}")
	public SingleResponse<ClassesInfoResp> info(@PathVariable("classId") String classId) {
		ClassesInfoResp classesInfoResp = classesInfoService.queryClassesInfo(Long.valueOf(classId));
		classesInfoResp.setPartyName(getUser().getUserName());
		return SingleResponse.of(classesInfoResp);
	}
	
	@ApiOperation(value = "查看老师", notes = "查看老师")
	@ApiImplicitParam(name = "classId", value = "班级ID", paramType = "path", dataType = "String")
	@RequiresPermissions("school:classesinfo:teacher")
	@GetMapping("/teacher/{classId}")
	public SingleResponse<ClassTeacherResp> teacher(@PathVariable("classId") String classId) {
		ClassTeacherResp classTeacherResp = classesInfoService.queryClassesTeacher(Long.valueOf(classId));
		return SingleResponse.of(classTeacherResp);
	}

	@ApiOperation(value = "修改班级", notes = "修改班级")
	@ApiImplicitParam(name = "request", value = "请求对象", required = true, dataType = "UpdateClassesInfoReq")
	@RequiresPermissions("school:classesinfo:update")
	@PostMapping("/update")
	public Response update(@RequestBody @Valid UpdateClassesInfoReq request) {
		request.setUpdateUserId(getUserId());
		classesInfoService.update(request);
		return Response.buildSuccess();
	}
	
	@ApiOperation(value = "批量删除班级", notes = "批量删除班级")
	@ApiImplicitParam(name = "request", value = "请求对象", required = true, dataType = "BatchDeleteClassesInfoReq")
	@RequiresPermissions("school:classesinfo:batchDelete")
	@PostMapping("/batchDelete")
	public Response batchDelete(@RequestBody @Valid BatchDeleteClassesInfoReq request) {
		request.setUpdateUserId(getUserId());
		classesInfoService.batchDelete(request);
		return Response.buildSuccess();
	}

	@ApiOperation(value = "删除班级", notes = "删除班级")
	@ApiImplicitParam(name = "classId", value = "班级ID", paramType = "path", dataType = "String")
	@RequiresPermissions("school:classesinfo:delete")
	@GetMapping("/delete/{classId}")
	public Response delete(@PathVariable("classId") String classId) {
		classesInfoService.delete(Long.valueOf(classId));
		return Response.buildSuccess();
	}
	
	@ApiOperation(value = "下载班级模板", notes = "下载班级模板")
	@RequiresPermissions("school:classesinfo:download")
	@GetMapping("/download")
	public void download(HttpServletResponse response) {
		String dir = System.getProperty("user.dir") + "/";
		String path = dir + "classes.xlsx";
		try {
			File file = new File(path);
			String filename = file.getName();

			InputStream fis = new BufferedInputStream(new FileInputStream(path));
			byte[] buffer = new byte[fis.available()];
			fis.read(buffer);
			fis.close();

			response.reset();

			response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
			response.addHeader("Content-Length", "" + file.length());
			OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			toClient.write(buffer);
			toClient.flush();
			toClient.close();
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException(BasicErrorCode.DEFINED_MSG, "下载模板失败");
		}
	}
	
	@ApiOperation(value = "批量导入班级", notes = "批量导入班级：xls xlsx")
	@RequestMapping(value = "/import", method = { RequestMethod.POST }, produces = "application/json;charset=UTF-8")
	@RequiresPermissions("school:classesinfo:import")
	@ResponseBody
	public MultiResponse batchImport(@RequestParam("file") @Valid MultipartFile upFile, @RequestParam("schoolId") @Valid Long schoolId) {
		String[] allowedType = { "application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" };
		boolean allowed = Arrays.asList(allowedType).contains(upFile.getContentType());
		if (!allowed) {
			throw new AppException(BasicErrorCode.FILE_FORMAT);
		}
		
		List<BatchImportClassesEntity> returnList = new ArrayList<>();
		List<BatchImportClassesEntity> saveList = new ArrayList<>();
		
		InputStream in = null;
		try {
			in = upFile.getInputStream();
			EasyExcel.read(in, BatchImportClassesEntity.class, new UploadClassesExcelListener()).sheet("Sheet1").doRead();
			for (BatchImportClassesEntity classes : UploadClassesExcelListener.list) {
				String message = "";
				boolean returnFlag = false;
				BatchImportClassesEntity entity = new BatchImportClassesEntity();
				BeanUtil.copyProperties(classes, entity);
				
				if (classesInfoService.queryClassNameExists(classes.getClassName(), getPartyId())) {
					message = classes.getClassName()+"已存在";
					returnFlag = true;
				}
				
				if (returnFlag) {
					entity.setMessage(message);
					returnList.add(entity);
				} else {
					saveList.add(entity);
				}
			}
			
			// 没有错误信息时批量保存
			if (0 == returnList.size()) {
				classesInfoService.batchSave(saveList, getPartyId(), getUserId(), schoolId);
			}
			
			UploadClassesExcelListener.list.clear();
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException(BasicErrorCode.DEFINED_MSG, "批量导入班级失败");
		}
		
		return MultiResponse.ofWithoutTotal(returnList);
	}
	
	@ApiOperation(value = "批量导出班级", notes = "批量导出班级：导出为xls文档")
	@ApiImplicitParam(name = "request", value = "请求对象", required = true, dataType = "QueryClassesInfoReq")
	@RequiresPermissions("school:classesinfo:import")
	@PostMapping("/export")
	public void export(@RequestBody QueryClassesInfoReq request, HttpServletResponse response) {
		request.setPartyId(getPartyId());
		request.setPageSize(5000);
		List<ClassesInfoExportResp> list = classesInfoService.queryExportList(request);
		if (list.size() != 0) {
			ExcelWriter writer = ExcelUtil.getWriter();
			
			// 自定义标题别名
			writer.addHeaderAlias("schoolName", "校区");
			writer.addHeaderAlias("sectionName", "学段");
			writer.addHeaderAlias("gradeName", "年级");
			writer.addHeaderAlias("className", "班级名称");
			writer.addHeaderAlias("typeName", "班级类型");
			writer.addHeaderAlias("termBeginTime", "入学年份");
			writer.addHeaderAlias("statusName", "状态");
			writer.addHeaderAlias("studentCount", "学生数");
			writer.write(list, true);
			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			String fileName = "班级";
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
			try {
				fileName = new String(fileName.getBytes(), "iso8859-1") + dateFormat.format(new Date());
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");
			ServletOutputStream out = null;
			try {
				out = response.getOutputStream();
				writer.flush(out, true);
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
			IoUtil.close(out);
		}
	}

}
